/**
 * 自动查询构建器装饰器
 * @author sun
 * @date 2024-03-30
 */

import { QueryOperator, DecoratorType, MetadataStore, IConditionDef } from './types';

// 使用WeakMap存储元数据，避免修改原始类结构和内存泄漏
const metadataMap = new WeakMap<object, MetadataStore>();

/**
 * 获取或创建目标类的元数据存储
 * @param target 目标类的构造函数
 */
function getMetadataStore(target: object): MetadataStore {
  if (!metadataMap.has(target)) {
    metadataMap.set(target, {});
  }
  return metadataMap.get(target)!;
}

/**
 * 获取类的查询条件元数据
 * @param target 类实例或构造函数
 */
export function getQueryMetadata(target: any): Record<string | symbol, IConditionDef> | undefined {
  const constructor = typeof target === 'function' ? target : target.constructor;
  return metadataMap.get(constructor)?.queryConditions;
}

/**
 * 查询条件装饰器
 * 用于标记类属性为查询条件
 * @param operator 查询操作符
 * @param defaultValue 默认值，可选
 */
export function Condition(operator: QueryOperator, defaultValue?: any): PropertyDecorator {
  return function (target: object, propertyKey: string | symbol): void {
    const metadata = getMetadataStore(target.constructor);

    if (!metadata.queryConditions) {
      metadata.queryConditions = {};
    }

    metadata.queryConditions[propertyKey] = {
      type: DecoratorType.CONDITION,
      operator,
      field: propertyKey.toString(),
      defaultValue,
    };
  };
}

/**
 * 逻辑与组装饰器
 * 用于标记类属性为AND条件组
 */
export function AndGroup(): PropertyDecorator {
  return function (target: object, propertyKey: string | symbol): void {
    const metadata = getMetadataStore(target.constructor);

    if (!metadata.queryConditions) {
      metadata.queryConditions = {};
    }

    metadata.queryConditions[propertyKey] = {
      type: DecoratorType.AND_GROUP,
      operator: QueryOperator.AND,
      field: propertyKey.toString(),
    };
  };
}

/**
 * 逻辑或组装饰器
 * 用于标记类属性为OR条件组
 */
export function OrGroup(): PropertyDecorator {
  return function (target: object, propertyKey: string | symbol): void {
    const metadata = getMetadataStore(target.constructor);

    if (!metadata.queryConditions) {
      metadata.queryConditions = {};
    }

    metadata.queryConditions[propertyKey] = {
      type: DecoratorType.OR_GROUP,
      operator: QueryOperator.OR,
      field: propertyKey.toString(),
    };
  };
}

/**
 * 范围查询装饰器
 * 用于标记类属性为范围查询条件
 * @param field 字段名，如不提供则使用属性名
 * @param minOperator 最小值操作符
 * @param maxOperator 最大值操作符
 */
export function Range(
  field?: string,
  minOperator = QueryOperator.GREATER_THAN_OR_EQUAL,
  maxOperator = QueryOperator.LESS_THAN_OR_EQUAL,
): PropertyDecorator {
  return function (target: object, propertyKey: string | symbol): void {
    const metadata = getMetadataStore(target.constructor);

    if (!metadata.queryConditions) {
      metadata.queryConditions = {};
    }

    metadata.queryConditions[propertyKey] = {
      type: DecoratorType.RANGE,
      operator: QueryOperator.BETWEEN, // 存储兼容性
      field: field || propertyKey.toString(),
      minOperator,
      maxOperator,
    };
  };
}

/**
 * 检查对象是否使用了查询装饰器
 * @param obj 要检查的对象
 */
export function hasQueryDecorators(obj: any): boolean {
  return (
    obj &&
    typeof obj === 'object' &&
    obj.constructor &&
    metadataMap.has(obj.constructor) &&
    !!metadataMap.get(obj.constructor)?.queryConditions
  );
}
